home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-02
/
pcxkit.zip
/
PCX.ASM
< prev
next >
Wrap
Assembly Source File
|
1992-01-06
|
10KB
|
214 lines
;============================
;Linkable module for PCX.PAS
;============================
DATA SEGMENT WORD
extrn datalength: word
extrn scratch: dword
extrn abuff0, abuff1: word
extrn is_CGA: byte
extrn page_addr: word
extrn video_index: word
extrn columncount: word
extrn plane: word
extrn repeatcount: byte
extrn bytes_per_line: word
writeproc dw (?)
DATA ENDS
CODE SEGMENT WORD PUBLIC
assume cs:code, ds:data
public decode_pcx
public decode_pcx256
LOCALS
;==========================================================================
;Here's how the data compression system works. Each byte is either image
;data or a count byte that tells how often the next image byte is repeated.
;The byte is image data if it follows a count byte, or if either of the top
;two bits is clear. Otherwise it is a count byte, with the count derived
;from the lower 6 bits.
GET_DATA_BYTE MACRO
@@getbyte: cmp si, datalength ;end of scratch buffer?
je @@exit ;yes, quit
push es ;save output address
push di
les di, scratch ;scratch start in ES:DI
add di, si ;add offset
mov al, [es:di] ;get byte from scratch
inc si ;increment index
pop di ;restore output address
pop es
cmp bl, 0 ;was prev. byte a count?
jg @@repeats ;yes, this is data
mov ah, al ;no, copy byte to AH
and ah, 192 ; and test high bits
cmp ah, 192
jne @@is_data ;not set, not a count
;It's a count byte
xor al, 192 ;get count from 6 low bits
mov bl, al ;store repeat count
jmp @@getbyte ;go get data byte
ENDM
;===================== Store CGA image in buffers ========================
STOREBYTE PROC NEAR
stosb ;AL into ES:DI, increment DI
inc dx ;increment column count
cmp dx, bytes_per_line
je row_ends ;end of a row
ret ;not end of row, so finished
row_ends: xor bp, 1 ;switch banks
cmp bp, 1 ;is bank 1?
je bank1 ;yes, jump
mov abuff1, di ;no, save index into bank 1
mov es, abuff0[2] ;load bank 0 segment
mov di, abuff0 ;load bank 0 index
xor dx, dx ;reset column counter
ret
bank1: mov abuff0, di ;save index into bank 0
mov es, abuff1[2] ;load bank 1 segment
mov di, abuff1 ;load bank 1 index
xor dx, dx ;reset column counter
ret
STOREBYTE ENDP
;====================== Write EGA/VGA image to video =====================
;The data in the .PCX file is organized by color plane, by line; that is,
;all the data for plane 0 for line 1, then for plane 1, line 1, etc.
;Writing the data to display memory is just a matter of masking out the
;other planes while one plane is being written to. This is done with the
;map mask register in the sequencer. All the other weird and wonderful
;registers in the EGA/VGA do just fine with their default settings, thank
;goodness.
WRITEBYTE PROC NEAR
stosb ;AL into ES:DI, inc DI
inc dx ;increment column
cmp dx, bytes_per_line ;reached end of scanline?
je doneline ;yes
ret ;no, go get a byte
doneline: shl bp, 1 ;shift to next plane
cmp bp, 8 ;done 4 planes?
jle setindex ;no
mov bp, 1 ;yes, reset plane to 1
jmp short setplane ; but don't reset index
setindex: sub di, dx ;reset to start of line
setplane: push ax ;save data in AL
cli ;clear interrupts
mov ax, bp ;plane is 1, 2, 4, or 8
mov dx, 3C5h ;sequencer data register
out dx, al ;mask out 3 planes
sti ;enable interrupts
pop ax ;restore data byte
xor dx, dx ;reset column count
ret
WRITEBYTE ENDP
;======================= Decode data from file ===========================
DECODE_PCX PROC NEAR
push bp
cmp is_CGA, 1
je CGAonly
mov bp, plane ;store plane in BP
mov es, page_addr ;video display segment
mov writeproc, offset writebyte ;choose EGA/VGA procedure
mov di, video_index ;output pointer
jmp short alltypes
CGAonly: mov writeproc, offset storebyte ;choose CGA procedure
;It's assumed that CGA files will require only one pass through the buffer,
;therefore output pointer is initialized to first row bank.
mov es, abuff0[2] ;segment of bank 0 buffer
mov di, abuff0 ;offset of buffer
mov bp, 0 ;bank in BP
alltypes: mov bl, repeatcount ;count in BL
mov dx, columncount ;column counter
xor cx, cx ;clean up CH for counter
mov si, cx ;initialize scratch ptr.
cld ;clear DF for stosb
;--------------------- Loop through scratch buffer ------------------------
get_data_byte ;macro
;It's a single data byte; call CGA or EGA routine once
@@is_data: call writeproc
jmp @@getbyte
;It's data to be written "count" times; call CGA or EGA routine repeatedly
@@repeats: mov cl, bl ;set loop counter
@@go: call writeproc
loop @@go ;write byte CX times
mov bl, 0 ;clear count byte
jmp @@getbyte
;----------------------- Finished with buffer ----------------------------
@@exit: mov plane, bp ;save status for next
mov repeatcount, bl ; run thru buffer
mov columncount, dx
mov video_index, di
pop bp
ret
DECODE_PCX ENDP
;==================== Decode data from 256-color file ====================
;The following procedure is fundamentally the same as DECODE_PCX, and the
;code could be made more compact by merging the two. I've done things this
;way solely in the interests of speed: it would waste time to call
;a "writeproc" procedure 64,000 times when that procedure consisted of just
;a single instruction.
DECODE_PCX256 PROC NEAR
mov es, page_addr ;video segment
mov bl, repeatcount ;count in BL
mov di, video_index ;index into video
xor cx, cx ;clean up loop counter
mov si, cx ;index into scratch
cld ;clear DF
;---------------------- Loop through scratch buffer -----------------------
get_data_byte ;macro
;It's a single data byte
@@is_data: stosb ;byte into video
jmp @@getbyte
;It's data to be written "count" times
@@repeats: mov cl, bl ;set counter
rep stosb ;write byte CX times
mov bl, 0 ;clear count byte
jmp @@getbyte
;------------------------- Finished with buffer --------------------------
@@exit: mov video_index, di ;save status for next
mov repeatcount, bl ; run thru buffer
ret
DECODE_PCX256 ENDP
;=========================================================================
CODE ENDS
END